import Queue, threading
import commands 
import time

import addrutil

# Golang version

def getLiveIPGo(prefix):
  resp = commands.getoutput("./getliveip %s" % prefix).split(' ')
  if len(resp) != 2 or (resp[1] != '0' and resp[1] != '1'):
    addrutil.log(int(time.time()), 0,
      '''getliveip Error: %s [%s].''' % (prefix, ' '.join(resp)))
    return ('', 0)

  ip, is_live = resp
  if is_live == '1':
    is_live = 1
  else:
    is_live = 0
  return (ip, is_live)

# python version

class PingIPThread(threading.Thread):
  def __init__ (self, ip_int, live_ip_queue, is_ipv6):
    threading.Thread.__init__(self)
    self.ip_str = addrutil.ip_int2str(ip_int, is_ipv6)
    self.live_ip_queue = live_ip_queue
    self.is_ipv6 = is_ipv6

  def run(self):
    if not self.is_ipv6:
      resp = commands.getoutput(
          "ping -c 1 -W 2 -q -n %s | grep '1 received'" % self.ip_str)
    else:
      resp = commands.getoutput(
          "ping6 -c 1 -W 2 -q -n %s | grep '1 received'" % self.ip_str)
    if '1 received' in resp:
      self.live_ip_queue.put(self.ip_str)

def getLiveIP(ipbeg, ipend, is_ipv6):
  threads = []
  live_ips = Queue.Queue()
  offset = 8
  threads.append(PingIPThread(ipbeg + 1, live_ips, is_ipv6))
  threads.append(PingIPThread(ipbeg + 2, live_ips, is_ipv6))
  if ipend - ipbeg > 4:
    threads.append(PingIPThread(ipbeg + 3, live_ips, is_ipv6))
    threads.append(PingIPThread(ipbeg + 4, live_ips, is_ipv6))
    while offset < ipend - ipbeg:
      threads.append(PingIPThread(ipbeg + offset - 2, live_ips, is_ipv6))
      threads.append(PingIPThread(ipbeg + offset - 3, live_ips, is_ipv6))
      threads.append(PingIPThread(ipbeg + offset + 1, live_ips, is_ipv6))
      threads.append(PingIPThread(ipbeg + offset + 2, live_ips, is_ipv6))
      offset <<= 1
      if len(threads) >= 96:
        break
    threads.append(PingIPThread(ipend - 1, live_ips, is_ipv6))
    threads.append(PingIPThread(ipend - 2, live_ips, is_ipv6))
  for t in threads:
    t.start()
  try:
    ip_str = live_ips.get(True, 2)
    return (ip_str, 1)
  except Exception:
    return (addrutil.ip_int2str((ipbeg | 1), is_ipv6), 0)

